package dy.com.第7章服务器优化.imp;

import dy.com.第7章服务器优化.Util.CloseUtils;
import dy.com.第7章服务器优化.core.IoArgs;
import dy.com.第7章服务器优化.core.IoProvider;
import dy.com.第7章服务器优化.core.Receiver;
import dy.com.第7章服务器优化.core.Sender;

import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.atomic.AtomicBoolean;

public class SocketChannelAdapter implements Sender, Receiver, Closeable {
    private final AtomicBoolean isClosed = new AtomicBoolean(false);
    private final SocketChannel channel;

    //用于通道的注册和线程池创建，并运行
    private final IoProvider ioProvider;
    //当channel关闭时，需要回调
    private final OnChannelStatusChangedListener listener;

    //参数监听者，用于监听buffer中数据变化，在开始和完成时
    private IoArgs.IoArgsEventListener receiveIoEventListener;
    private IoArgs.IoArgsEventListener sendIoEventListener;

    public SocketChannelAdapter(SocketChannel channel, IoProvider ioProvider, OnChannelStatusChangedListener listener) throws IOException {
        this.channel = channel;
        this.ioProvider = ioProvider;
        this.listener = listener;

        channel.configureBlocking(false);
    }

    @Override
    //用于接收数据，将channel注册，并将注册得到的key和runnable任务绑定到hashmap中
    public boolean receiveAsync(IoArgs.IoArgsEventListener listener) throws IOException {
        if (isClosed.get()) {
            throw new IOException("current channel is closed");

        }
        receiveIoEventListener = listener;
        return ioProvider.registerInput(channel, inputCallback);
    }

    @Override
    public boolean sendAsync(IoArgs args, IoArgs.IoArgsEventListener listener) throws IOException {
        if (isClosed.get()) {
            throw new IOException("current channel is closed");

        }
        sendIoEventListener = listener;
        //注入发送的数据
        outputCallback.setAttach(args);
        return ioProvider.registerOutput(channel, outputCallback);

    }

    @Override
    public void close() throws IOException {
        if (isClosed.compareAndSet(false, true)) {
            //解除注册回调
            ioProvider.unRegisterInput(channel);
            ioProvider.unRegisterInput(channel);
            //关闭channel
            CloseUtils.close(channel);
            //回调当前channel已关闭
            listener.onChannelCLosed(channel);

        }
    }
    //定义要执行的输入任务
    private final IoProvider.HandleInputCallback inputCallback = new IoProvider.HandleInputCallback() {
        @Override
        protected void canProviderInput() {
            if (isClosed.get()) {
                return;
            }

            IoArgs args = new IoArgs();
            IoArgs.IoArgsEventListener listener = SocketChannelAdapter.this.receiveIoEventListener;

            if (listener != null) {
                listener.onStarted(args);
            }
            try {
                //读取
                if (args.read(channel) > 0 && listener != null) {
                    //读取完成回调
                    listener.OnCompleted(args);
                }else{
                    throw new IOException("不能再读取数据");
                }
            } catch (Exception ignored) {
                CloseUtils.close(SocketChannelAdapter.this);
            }
        }
    };
    private final IoProvider.HandlerOutputCallback outputCallback = new IoProvider.HandlerOutputCallback() {
        @Override
        protected void canProviderOutput(Object attach) {
            if (isClosed.get()) {
                return;
            }
            sendIoEventListener.OnCompleted(null);
        }
    };

    public interface OnChannelStatusChangedListener {
        void onChannelCLosed(SocketChannel channel);
    }
}
